package com.tian.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.tian.dto.PayNotifyReqDto;
import com.tian.dto.WxPrePayReqDto;
import com.tian.entity.ChargerRecord;
import com.tian.entity.PayOrder;
import com.tian.entity.User;
import com.tian.enums.*;
import com.tian.mapper.ChargerRecordMapper;
import com.tian.mapper.PayOrderMapper;
import com.tian.mapper.UserMapper;
import com.tian.service.WxPayService;
import com.tian.util.*;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @author tianwc  公众号：java后端技术全栈、面试专栏
 * @version 1.0.0
 * 博客地址：<a href="http://woaijava.cc/">博客地址</a>
 * <p>
 * 微信支付
 */
@Slf4j
@Service
public class WxPayServiceImpl implements WxPayService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private ChargerRecordMapper chargerRecordMapper;
    @Resource
    private PayOrderMapper payOrderMapper;

    @Transactional(rollbackFor = WxPayException.class)
    @Override
    public CommonResult<Boolean> createPrePayOrder(WxPrePayReqDto wxPrePayReqDto) {
        User user = UserCacheUtil.getUser();
        ChargerRecord chargerRecord = chargerRecordMapper.selectByUserId(user.getId());

        String orderNo = DateUtil.getOrderNum("CDZ") + RandomUtil.randomNumbers(6);

        PayOrder payOrder = new PayOrder();
        payOrder.setCreateTime(new Date());
        payOrder.setMoney(chargerRecord.getMoney());
        payOrder.setOrderNo(orderNo);
        payOrder.setChargerRecordId(chargerRecord.getId());
        payOrder.setBusinessType(PayBusinessTypeEnum.PAY_CHARGER.getBusiness());
        payOrder.setStatus(WxPayStatusEnum.INIT.getStatus());

        payOrderMapper.insert(payOrder);
        chargerRecord.setPayStatus(PayStatusEnum.UN_PAY.getPayStatus());
        chargerRecordMapper.updateByPrimaryKey(chargerRecord);
        return CommonResult.failed(ResultCode.FAILED);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public CommonResult<Boolean> payNotify(PayNotifyReqDto payNotifyReqDto) {
        String orderNo = payNotifyReqDto.getOrderNo();
        if (StringUtil.isEmpty(orderNo) || StringUtil.isBlank(payNotifyReqDto.getThirdTradeNo())) {
            return CommonResult.failed(ResultCode.PARAMETER_EMPTY);
        }

        PayOrder payOrder = payOrderMapper.selectByOrderNo(orderNo);

        if (payOrder == null) {
            log.error("支付回调通知，orderNo={} 不存在", orderNo);
            return CommonResult.failed(ResultCode.VALIDATE_FAILED);
        }

        ChargerRecord chargerRecord = chargerRecordMapper.selectByPrimaryKey(payOrder.getChargerRecordId());

        //分布式锁锁住该用户账号---
        String key = RedisConstantPre.BALANCE_LOCK_PRE + orderNo;
        RLock rLock = redissonClient.getLock(key);

        rLock.lock();
        try {
            User user = userMapper.getUserById(payOrder.getChargerRecordId());

            //修改状态
            payOrder.setPayOrder(payNotifyReqDto.getThirdTradeNo());
            payOrder.setStatus(WxPayStatusEnum.SUCCESS.getStatus());
            payOrderMapper.updateByPrimaryKey(payOrder);
            chargerRecord.setPayStatus(PayStatusEnum.PAY_FINISH.getPayStatus());
            chargerRecordMapper.updateByPrimaryKey(chargerRecord);

            //给用户账户添加余额
            user.setMoney(user.getMoney().add(payOrder.getMoney()));
            userMapper.updateUser(user);
            return CommonResult.success(Boolean.TRUE);
        } finally {
            rLock.unlock();
        }
    }
}
